iT邦幫忙

0

Day 51 (Node.js)

  • 分享至 

  • xImage
  •  

1.res.send()和 res.end()的差別

(1)res.write + res.end

     http.createServer(function (req, res) {
         if(results[0])[
             res.write("<html>")
             res.write("<head>")
             //...
             res.write("</html>")
             res.end();
     }

現在都直接用res.render("index.ejs",{})輸出網頁

(2)res.send = res.write + res.end
後來大家都直接用 send

     app.get("/", function (req, res) {
       res.send("OK, Home page....");
     }) 

2.資料庫Update (檔案Lab > 15_資料庫_UpdateDelect)

(1)

npm install
npm start (nodemon app.js)

(2)Update
當使用者點擊編輯:資料放在編輯頁面上SPA(沒有另跳頁面)
特性:使用JS編輯(rel="modal:open"),server只給值

(3)HTML

     <!-- modal:open 另跳視窗開啟 -->
     <a href="#ex1" rel="modal:open"> 
     <button  onclick="Edit(<%= item.id%>)">編輯</button></a> 
     <button onclick="Delete(<%= item.id%>)">刪除</button>

(4)index.ejs > 取值

        function Edit(id) {
            $.ajax({
                url: "/detail/"+id,   
                type: "GET",
                success: function(res) {
                    var res = JSON.parse(res)
                    //res.data 指 success.data
                    //將值傳遞進input裏頭
                    $("input[name='id']").val(res.data.id)  
                    $("input[name='name']").val(res.data.name)
                    $("input[name='phone']").val(res.data.phone)
                    $("input[name='address']").val(res.data.address)
                    $("input[name='adult_mask']").val(res.data.adult_mask)
                    $("input[name='child_mask']").val(res.data.child_mask)
                },
                error: function() {
                    alert("系統錯誤!")
                },
            })
        }

(5)index.js > SQL語法
1.取值顯示在編輯頁面上,2.頁面回傳Success or Error

    index.get('/detail/:id([0-9]+)', function(req, res){
    var sql = `SELECT * FROM inventory WHERE id = ?;`
    var data = [req.params.id]
    // exec MySQL的引用
    db.exec(sql, data, function(results, fields) {
        if(results[0]){  //第0筆資料
            res.end(
                JSON.stringify(new Success(results[0]))
            )
        } else {
            res.end(
                JSON.stringify(new Error('no result'))
            )
        }
      })
    })

(6)response.js > Success or Error輸出data(此處)或message

    class Success {
      constructor(data, message) {
        if(typeof data === 'string') {
            this.message = data
            data = null
            message = null
        }
        if(data) {
            this.data = data
        }
        if(message) {
            this.message = message
        }
        this.errno = 1
      }  
    }  

(7)編輯送出

        $('#submit').on('click', function() {
            //整理表單資料到變數
            var data = $('#form').serializeArray()  
            //form表單內資料轉成陣列
            JSONData = serializeToJSON(data) 
                     
            //用post方法丟json格式的data到 /update 
            //陣列資料轉Json物件 ajax才能使用
            $.ajax({
                url: "/update",  //index.js > exec方法輸出
                type: "POST",
                contentType: "application/json; charset=utf-8",
                data: JSONData,

                success: function(res) {
                    var res = JSON.parse(res)
                    if(res.errno === 1) {                         
                        alert(res.message +"更新成功!")
                        location.reload()
                    } else if(res.errno === 0) {
                        alert("更新失敗!")
                    }
                },
                error: function() {
                    alert("系統錯誤!")
                }
            })
        })

(8)response.js > Success or Error輸出data或message(此處)

    class Success {
      constructor(data, message) {
        if(typeof data === 'string') {
            this.message = data
            data = null
            message = null
        }
        if(data) {
            this.data = data
        }
        if(message) {
            this.message = message
        }
        this.errno = 1
      }  
    }  

3.資料庫Delect (檔案Lab > 15_資料庫_UpdateDelect)

(1)HTML

     <!-- modal:open 另跳視窗開啟 -->
     <a href="#ex1" rel="modal:open"> 
     <button  onclick="Edit(<%= item.id%>)">編輯</button></a> 
     <button onclick="Delete(<%= item.id%>)">刪除</button>

(2)index.ejs

        function Delete(id) {
            var JSONData = {"id": id}
            JSONData = JSON.stringify(JSONData)
            $.ajax({
                url: "/delete",
                type: "POST",
                contentType: "application/json; charset=utf-8",
                data: JSONData,
                success: function(res) {
                    var res = JSON.parse(res)
                    if(res.errno === 1) {
                        alert("刪除成功!")
                        location.reload()
                    } else if(res.errno === 0) {
                        alert("刪除失敗!")
                    }
                },
                error: function() {
                    alert("系統錯誤!")
                }
            })
        }

(3) index.js > exec方法輸出

      index.post('/delete', function(req, res){
          var body = req.body
          var sql = `DELETE FROM inventory WHERE id = ?;`
          var data = [parseInt(body.id)] //轉數值
          db.exec(sql, data, function(results, fields) {
              //使用affectedRows,判斷是否有被刪除
              if(results.affectedRows){
                  res.end(
                            JSON.stringify(new Success('delete success'))
                  )
              } else {
                  res.end(
                      JSON.stringify(new Error('delete failed'))
                  )
              }
          })
      })

(3)response.js > Success or Error輸出data或message(此處)

    class Success {
      constructor(data, message) {
        if(typeof data === 'string') {
            this.message = data
            data = null
            message = null
        }
        if(data) {
            this.data = data
        }
        if(message) {
            this.message = message
        }
        this.errno = 1
      }  
    } 

4.Bludbird (檔案JavaScript > 09_promise)

(1)promise使用then的方法
https://ithelp.ithome.com.tw/upload/images/20210818/20137684VbY6QW0Bd5.jpg

(2)promise解決Callback Hell
bludbird套件使用promise解決Callback Hell(就不會曹套)

(3)promise物件

    function longTimeWork(workFine = true, errorMessage = "test") {
        return new Promise( (resolve, reject) => {   // 3.取得承諾物件
            setTimeout( () => {
                (workFine) ? resolve(200) : reject(errorMessage); 
           }, 1000);
        })
    }

(4)async + await (promise才有await)
成功//200
失敗//test02

    async function usingLongTimeWork() {
        try {
            var result = await longTimeWork(workFine, "test02"); 
            console.log(result);
        }
        catch (e) {
            console.log(e); //"test"
        }
    
    }

5.Promise await + async(必要)(檔案JavaScript > 09_promise)

await用處:等待時間,計算倉庫剩幾張票,再繼續賣剩下的票
避免同時多人同時購票,且電腦有時間計算票數

(1)取得承諾物件

     function longTimeWork(workFine = true, errorMessage = "test") {
         return new Promise( (resolve, reject) => {   // 
             setTimeout( () => {
                 (workFine) ? resolve(200) : reject(errorMessage); // 5.收到,跑程式 
             }, 1000); //1000 = 1秒
         })
     }

(1-2)非同步 async + await

     async function main2() {       
         var p = await longTimeWork(true, "test"); // 2.呼叫function  ; await
         console.log(p);    //200
     }
     main2() 

(1-3)想要有 成功 與 失敗 的輸出分類時

     function usingLongTimeWork() {
         longTimeWork(true, "test")  // try true/false
         .then(function (e) {  // 成功時:resolve(200) ; e變數 
             console.log('ok2yoyo'+ e);  //ok2yoyo200                  
         })
         .catch(function (e) {  // 失敗時:reject(errorMessage)
             console.log('ok3'+ e);
         })
     }

(2)02_AsyncAwait:(1)的綜合簡寫 + =>函式
Promise + await (無須then 已内建)

        function longTimeWork(workFine = true, errorMessage = "test") {
            return new Promise( (resolve, reject) => {    //取得承諾物件
                setTimeout( () => {
                    (workFine) ? resolve(200) : reject(errorMessage);
                }, 1000);
            })
        }


        //想要有 成功 與 失敗 的輸出分類時 
        async function usingLongTimeWork() {
            try {
                //longTimeWork( true / false , "test")                      
                var result = await longTimeWork(false, "test"); 
                console.log(result);
            }
            catch (e) {
                console.log(e); //"test"
            }
        
            console.log("123")
        }

        usingLongTimeWork();

(3)03_testOnHtml (Promise + await)

      function longTimeWork(workFine = true, errorMessage = "test") {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            workFine ? resolve(200) : reject(errorMessage);
          }, 5000);
        });
      }

      async function usingLongTimeWork(isOK) {
        try {
          var result = await longTimeWork(isOK, "test");
          console.log(result);
        } catch (e) {
          console.log(e);
        }
      }

      console.log("flag A");
      usingLongTimeWork(true);   //200(五秒後出現)
      console.log("flag B");
      usingLongTimeWork(false);  //test(五秒後出現)
      console.log("flag C");

(4)非同步 async + await(總共用5秒)

    async function living() {
        var total = 0;

        var result1 = await happy(200, 2000);
        // result1 跑完才往下執行
        console.log(result1);
        var result2 = await sad(-100, 3000);
        // 等result1跑完 result2 才執行

        console.log(result2);
        total = result1 + result2;
        console.log("total:", total);
    }    

(5)同步進行 async + 變數 + await(總共用3秒)

    async function living() {
        var promise1 = happy(200, 2000);
        var promise2 = sad(-100, 3000);
        var result1 = await promise1;
        var result2 = await promise2;
       //同時進行,但等待完才將答案送到結果,所以只花3秒鐘
        var total = result1 + result2;
        console.log("total:", total);
    }

(6)5進化版[,]

    async function living() {
    var promise1 = happy(200, 2000);
    var promise2 = sad(-100, 3000);

    let [result1, result2] = 
      await Promise.all([promise1, promise2]);  //需要同步進行時,塞在同一的陣列

    var total = result1 + result2;
    console.log("total:", total);
    }

(7)更偷懶 直接塞方法(省略倉庫)

    async function living() {

        let [result1, result2] = 
          await Promise.all([happy(200, 2000), sad(-100, 3000)]);  //省略倉庫

        var total = result1 + result2;
        console.log("total:", total);
    }

6.await使用 Demo > ticket資料夾

舉例:1個商品有3個人同時購買
但剛好在同一秒鐘,三個人同時點下購入,會變成3個人都交易成功
為了避免,就要使用這個方法

(1)Demo_Multi_Users(SQL_Server)
顧客買商品各一個:Demo_Multi_Users(SQL_Server) > ClientA、B、C.sql
此時會導致資料庫誤讀,因為同時購買

    select @count = UnitsInStock from Products where ProductID = 1
    waitfor delay '00:00:15' //同時間00:00:15購買
    update Products set UnitsInStock = @count - 1 where ProductID = 1

老師用sql server,但MySQL應該也可以使用

(2)新增資料庫 MySQL

    create database ticketdb default character set utf8;
    use ticketdb;
    create table concert
    (
      concertId int auto_increment not null primary key,
      concertName varchar(30),
      count int
    );
    
    insert into concert (concertName, count) values 
      ('Jody''s last conert', 1000),
      ('Jeter say good-bye', 2000);

    select * from concert;

(3) > npm start

      "scripts": {
        "start": "nodemon ./bin/www"
      },

(4) ticket.js (await + FOR UPDATE)

    await req.mysql.queryAsync("start transaction", []);  
    //交易機制SQL備份,之後rollback恢復(大家同時搶票,同時交易會同時產生訂單(錯誤),系統出錯rollback恢復,再搶一次)

    var data = await req.mysql.queryAsync("select * from concert where concertId = 1 for update", []); 
      // FOR UPDATE 鎖資料鎖到交易完成  
      // 多人鎖定控制 更改 (票只剩一張,只能看不能下單)
      // 為了確定買票只有一個人正在進行

7. CORS - SOP同源政策

去別人的伺服器抓資料

(1)通訊協定、機器名稱、port號三者都必須相同才符合同源政策

(2)

    var cors = require("cors"); //引用cors物件

    const corsOptions = {
        origin: [  //把別人的伺服器放進來,跟人家要資料(別人可以拒絕
            'http://www.beauty.com',
            'http://localhost',
        ],
        methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS'
    };

methods:
Create → POST
Read → GET
Update → PUT
Delete → DELETE


8.callback - function倉庫

      function lab3(x, callback) {
        x += 1;
        callback(x);
      }


      lab3(20, function (value) {
        //value = 10
        alert(value);
        console.log(value);
      });

      lab3(30, (value) => {
        alert(value);
      });

      lab3(40, (value) => alert(value));

9.變數 vs 參數()

變數

     var a =1;

參數

      function lab(x) {
        x += 1;
        alert(x);
      }

      lab(10);

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言